import os
import re
import json
import time
import requests
import subprocess
import asyncio
from datetime import datetime
from urllib.parse import unquote

# ======================================= 全局配置区域 ============================================
# 加载环境变量
TIMEOUT = 15000  # 超时时间(毫秒)
print("加载sendNotify，当前版本: 20240612")

# ======================================= Go-cqhttp 配置 ============================================
GOBOT_URL = os.environ.get('GOBOT_URL', '')
GOBOT_TOKEN = os.environ.get('GOBOT_TOKEN', '')
GOBOT_QQ = os.environ.get('GOBOT_QQ', '')

# ======================================= 微信Server酱配置 =========================================
SCKEY = os.environ.get('PUSH_KEY', '')

# ======================================= Bark App配置 =============================================
BARK_PUSH = os.environ.get('BARK_PUSH', '')
BARK_SOUND = os.environ.get('BARK_SOUND', '')
BARK_GROUP = os.environ.get('BARK_GROUP', 'QingLong')

# ======================================= Telegram配置 =============================================
TG_BOT_TOKEN = os.environ.get('TG_BOT_TOKEN', '')
TG_USER_ID = os.environ.get('TG_USER_ID', '')
TG_PROXY_HOST = os.environ.get('TG_PROXY_HOST', '')
TG_PROXY_PORT = os.environ.get('TG_PROXY_PORT', '')
TG_PROXY_AUTH = os.environ.get('TG_PROXY_AUTH', '')
TG_API_HOST = os.environ.get('TG_API_HOST', 'api.telegram.org')

# ======================================= 钉钉配置 =================================================
DD_BOT_TOKEN = os.environ.get('DD_BOT_TOKEN', '')
DD_BOT_SECRET = os.environ.get('DD_BOT_SECRET', '')

# ======================================= 企业微信机器人配置 ========================================
QYWX_KEY = os.environ.get('QYWX_KEY', '')

# ======================================= 企业微信应用消息配置 ======================================
QYWX_AM = os.environ.get('QYWX_AM', '')

# ======================================= iGot配置 =================================================
IGOT_PUSH_KEY = os.environ.get('IGOT_PUSH_KEY', '')

# ======================================= PushPlus配置 =============================================
PUSH_PLUS_TOKEN = os.environ.get('PUSH_PLUS_TOKEN', '')
PUSH_PLUS_USER = os.environ.get('PUSH_PLUS_USER', '')

# ======================================= WxPusher配置 =============================================
WP_APP_TOKEN = os.environ.get('WP_APP_TOKEN', '')
WP_TOPICIDS = os.environ.get('WP_TOPICIDS', '')
WP_UIDS = os.environ.get('WP_UIDS', '')
WP_URL = os.environ.get('WP_URL', '')
WP_APP_TOKEN_ONE = os.environ.get('WP_APP_TOKEN_ONE', '')
WP_UIDS_ONE = os.environ.get('WP_UIDS_ONE', '')

# ======================================= Gotify配置 ===============================================
GOTIFY_URL = os.environ.get('GOTIFY_URL', '')
GOTIFY_TOKEN = os.environ.get('GOTIFY_TOKEN', '')
GOTIFY_PRIORITY = int(os.environ.get('GOTIFY_PRIORITY', 0))

# ======================================= BncrBot配置 ==============================================
BNCR_HOST = os.environ.get('BncrHost', '')
BNCR_TOKEN = os.environ.get('BncrToken', '')

# 初始化变量
PushErrorTime = 0
strTitle = ""
ShowRemarkType = os.environ.get('NOTIFY_SHOWNAMETYPE', '1')
Notify_NoCKFalse = os.environ.get('NOTIFY_NOCKFALSE', 'false')
Notify_NoLoginSuccess = os.environ.get('NOTIFY_NOLOGINSUCCESS', 'false')
UseGroupNotify = 1

# ======================================= 辅助函数 =================================================
def getRemark(remarks):
    """提取备注信息并清理"""
    if remarks and isinstance(remarks, str):
        return remarks.strip()
    return ""

def getQLinfo(cookie, created, updated, remarks):
    """生成青龙面板信息"""
    info = ""
    if created:
        created_time = datetime.fromtimestamp(created/1000).strftime('%Y-%m-%d %H:%M:%S')
        info += f"\n创建时间: {created_time}"
    
    if updated:
        updated_time = datetime.fromtimestamp(updated/1000).strftime('%Y-%m-%d %H:%M:%S')
        info += f"\n更新时间: {updated_time}"
    
    if remarks:
        info += f"\n备注: {remarks}"
    
    return info

def getPtPin(text):
    """从文本中提取PtPin"""
    match = re.search(r'pt_pin=([^;\s]+)', text)
    return unquote(match.group(1)) if match else None

def getPtPinFromCookie(cookie):
    """从Cookie中提取PtPin"""
    match = re.search(r'pt_pin=([^;\s]+)', cookie)
    return unquote(match.group(1)) if match else None

async def isLoginByX1a0He(cookie):
    """检查CK是否有效"""
    try:
        headers = {'Cookie': cookie}
        response = requests.get('https://me-api.jd.com/user_new/info/GetJDUserInfoUnion', 
                               headers=headers, timeout=10)
        data = response.json()
        return data.get('retcode') == '0'
    except Exception:
        return False

async def disableCk(ck_id):
    """禁用CK"""
    try:
        ql_url = os.environ.get('QL_URL', 'http://localhost:5600')
        ql_client_id = os.environ.get('QL_CLIENT_ID', '')
        ql_client_secret = os.environ.get('QL_CLIENT_SECRET', '')
        
        # 获取青龙API token
        auth_data = {'client_id': ql_client_id, 'client_secret': ql_client_secret}
        auth_res = requests.post(f'{ql_url}/open/auth/token', json=auth_data)
        token = auth_res.json().get('data', {}).get('token')
        
        # 禁用CK
        disable_data = {'_id': ck_id, 'status': 1}
        headers = {'Authorization': f'Bearer {token}'}
        disable_res = requests.put(f'{ql_url}/open/envs', json=disable_data, headers=headers)
        return disable_res.json()
    except Exception as e:
        return {"code": 500, "message": str(e)}

async def getEnvs():
    """获取环境变量列表"""
    try:
        ql_url = os.environ.get('QL_URL', 'http://localhost:5600')
        ql_client_id = os.environ.get('QL_CLIENT_ID', '')
        ql_client_secret = os.environ.get('QL_CLIENT_SECRET', '')
        
        # 获取青龙API token
        auth_data = {'client_id': ql_client_id, 'client_secret': ql_client_secret}
        auth_res = requests.post(f'{ql_url}/open/auth/token', json=auth_data)
        token = auth_res.json().get('data', {}).get('token')
        
        # 获取环境变量
        headers = {'Authorization': f'Bearer {token}'}
        envs_res = requests.get(f'{ql_url}/open/envs', headers=headers)
        return envs_res.json().get('data', [])
    except Exception as e:
        print(f"获取环境变量失败: {str(e)}")
        return []

async def getEnvByPtPin(pt_pin):
    """通过PtPin获取环境变量"""
    envs = await getEnvs()
    for env in envs:
        cookie = env.get('value', '')
        env_pt_pin = getPtPinFromCookie(cookie)
        if env_pt_pin == pt_pin:
            return env
    return None

def loadWxPusherUidFile():
    """加载WxPusherUid.json文件"""
    strUidFile = '/ql/data/scripts/CK_WxPusherUid.json' if os.path.exists('/ql/data/config/auth.json') else '/ql/scripts/CK_WxPusherUid.json'
    
    if os.path.exists(strUidFile):
        print("检测到一对一Uid文件WxPusherUid.json，载入...")
        try:
            with open(strUidFile, 'r', encoding='utf-8') as f:
                return json.load(f)
        except Exception as e:
            print(f"加载WxPusherUid文件失败: {str(e)}")
    return []

# ======================================= WxPusher一对一推送 =============================================
async def sendNotifybyWxPucher(text, desp, PtPin, author='\n\n本通知 By 智推送', strsummary=""):
    """WxPusher一对一推送"""
    if not WP_APP_TOKEN_ONE:
        print("未配置WP_APP_TOKEN_ONE，跳过WxPusher一对一推送")
        return
    
    # 加载WxPusherUid文件
    TempCKUid = loadWxPusherUidFile()
    
    # 查找对应PtPin的Uid
    uid = None
    for item in TempCKUid:
        if item.get('pt_pin') == PtPin:
            uid = item.get('uid')
            break
    
    if not uid:
        print(f"未找到PtPin: {PtPin} 对应的WxPusher Uid")
        return
    
    # 构建请求数据
    url = "https://wxpusher.zjiecode.com/api/send/message"
    headers = {'Content-Type': 'application/json'}
    data = {
        "appToken": WP_APP_TOKEN_ONE,
        "content": f"{text}\n\n{desp}{author}",
        "summary": strsummary or text,
        "contentType": 1,
        "uids": [uid],
        "url": WP_URL or ""
    }
    
    try:
        response = requests.post(url, headers=headers, data=json.dumps(data), timeout=10)
        result = response.json()
        if result.get('code') == 1000:
            print("WxPusher一对一推送成功")
        else:
            print(f"WxPusher一对一推送失败: {result.get('msg')}")
    except Exception as e:
        print(f"WxPusher一对一推送异常: {str(e)}")

# ======================================= 主通知函数 =============================================
async def sendNotify(text, desp, params=None, author='\n\n本通知 By ccwav Mod', strsummary=""):
    if params is None:
        params = {}
    
    print("开始发送通知...")
    
    # 初始化通知渠道开关
    use_serverNotify = True
    use_pushPlusNotify = True
    use_BarkNotify = True
    use_tgBotNotify = True
    use_ddBotNotify = True
    use_qywxBotNotify = True
    use_qywxamNotify = True
    use_iGotNotify = True
    use_gobotNotify = True
    use_WxPusher = True
    
    # 过滤脚本通知
    if 'NOTIFY_FILTERBYFILE' in os.environ:
        no_notify = os.environ['NOTIFY_FILTERBYFILE'].split('&')
        # 此处简化实现，实际需根据调用者文件名判断
        if any(key in text for key in no_notify):
            print(f"{text} 含有关键字，不推送")
            return
    
    global UseGroupNotify, strTitle, GOBOT_URL, GOBOT_TOKEN, GOBOT_QQ, SCKEY, BARK_PUSH, BARK_SOUND
    global TG_BOT_TOKEN, TG_USER_ID, DD_BOT_TOKEN, DD_BOT_SECRET, QYWX_KEY, QYWX_AM, IGOT_PUSH_KEY
    global PUSH_PLUS_TOKEN, PUSH_PLUS_USER, WP_APP_TOKEN, WP_TOPICIDS, WP_UIDS, WP_URL, Notify_CKTask
    global Notify_SkipText, GOTIFY_URL, GOTIFY_TOKEN, BNCR_HOST, BNCR_TOKEN
    
    # 初始化变量
    UseGroupNotify = 1
    strTitle = ""
    Notify_CKTask = os.environ.get('NOTIFY_CKTASK', '')
    Notify_SkipText = os.environ.get('NOTIFY_SKIP_TEXT', '').split('&') if 'NOTIFY_SKIP_TEXT' in os.environ else []
    
    # 跳过特定内容
    if any(skip in desp for skip in Notify_SkipText):
        print("检测到屏蔽关键字，跳过推送")
        return
    
    # CK失效处理
    if "cookie已失效" in text or "重新登录获取" in desp or text == "Ninja 运行通知":
        if Notify_NoCKFalse == "true" and text != "Ninja 运行通知":
            print("NOTIFY_NOCKFALSE=true，不发送CK失效通知")
            return
        
        if Notify_CKTask:
            print("触发CK脚本，开始执行...")
            subprocess.run(Notify_CKTask, shell=True)
        
        # 自动检查CK逻辑
        if os.environ.get('NOTIFY_AUTOCHECKCK') == "true" and ("cookie已失效" in text or "重新登录获取" in desp):
            print("捕获CK过期通知，尝试处理...")
            strPtPin = getPtPin(text)
            if strPtPin:
                env = await getEnvByPtPin(strPtPin)
                if env and env.get('status') == 0:
                    if not await isLoginByX1a0He(env['value']):
                        # 确定账号分组
                        group = ""
                        for i in range(2, 5):
                            env_var = os.environ.get(f'BEANCHANGE_USERGP{i}', '')
                            if env_var and strPtPin in env_var.split('&'):
                                text = f"京东CK检测#{i}"
                                group = f"分组{i}"
                                break
                        else:
                            text = "京东CK检测"
                        
                        # 禁用CK
                        ck_id = env.get('id') or env.get('_id')
                        result = await disableCk(ck_id)
                        
                        # 构建通知消息
                        msg = f"京东账号 {strPtPin} 已失效"
                        if result.get('code') == 200:
                            msg += ",自动禁用成功!"
                        else:
                            msg += ",自动禁用失败!"
                        
                        msg += "\n如果要继续挂机，请重新登录账号，自助提交Cookie."
                        msg += f"\n任务标题：{text}"
                        
                        # 添加温馨提示
                        if os.environ.get('CHECKCK_ALLNOTIFY'):
                            msg += f"\n\n【✨✨温馨提示✨✨】\n{os.environ['CHECKCK_ALLNOTIFY']}"
                        
                        # 发送一对一通知
                        if WP_APP_TOKEN_ONE:
                            await sendNotifybyWxPucher("账号过期下线通知", msg, strPtPin)
    
    # 特殊标题处理
    if "已可领取" in text:
        if "农场" in text:
            strTitle = "东东农场领取"
        else:
            strTitle = "东东萌宠领取"
    elif "汪汪乐园养joy" in text:
        strTitle = "汪汪乐园养joy领取"
    elif text == "京喜工厂" and "元造进行兑换" in desp:
        strTitle = "京喜工厂领取"
    elif "任务" in text and ("新增" in text or "删除" in text):
        strTitle = "脚本任务更新"
    
    strTitle = strTitle or text
    
    # 跳过特定通知
    notify_skip_list = os.environ.get('NOTIFY_SKIP_LIST', '').split('&')
    if strTitle in notify_skip_list:
        print(f"{strTitle} 在推送黑名单中，已跳过")
        return
    
    # 分组通知配置
    for group_num in range(2, 20):
        group_list = os.environ.get(f'NOTIFY_GROUP{group_num}_LIST', '')
        if group_list and strTitle in group_list.split('&'):
            print(f"{strTitle} 在群组{group_num}推送名单中")
            UseGroupNotify = group_num
            break
    
    # 自定义通知配置
    if 'NOTIFY_CUSTOMNOTIFY' in os.environ:
        custom_notify = os.environ['NOTIFY_CUSTOMNOTIFY']
        custom_items = custom_notify.strip('[]').split(',')
        for item in custom_items:
            parts = item.split('&')
            if len(parts) > 1 and strTitle == parts[0]:
                print("检测到自定义设定,开始执行配置...")
                if "组" in parts[1]:
                    UseGroupNotify = int(parts[1].replace("组", ""))
                    print(f"自定义设定强制使用组{UseGroupNotify}配置通知...")
                
                # 处理通知渠道开关
                if len(parts) > 2:
                    print("关闭所有通知渠道...")
                    use_serverNotify = False
                    use_pushPlusNotify = False
                    use_BarkNotify = False
                    use_tgBotNotify = False
                    use_ddBotNotify = False
                    use_qywxBotNotify = False
                    use_qywxamNotify = False
                    use_iGotNotify = False
                    use_gobotNotify = False
                    use_WxPusher = False
                    
                    for channel in parts[2:]:
                        if channel == "Server酱":
                            use_serverNotify = True
                        elif channel == "pushplus":
                            use_pushPlusNotify = True
                        elif channel == "Bark":
                            use_BarkNotify = True
                        elif channel == "TG机器人":
                            use_tgBotNotify = True
                        elif channel == "钉钉":
                            use_ddBotNotify = True
                        elif channel == "企业微信机器人":
                            use_qywxBotNotify = True
                        elif channel == "企业微信应用消息":
                            use_qywxamNotify = True
                        elif channel == "iGotNotify":
                            use_iGotNotify = True
                        elif channel == "gobotNotify":
                            use_gobotNotify = True
                        elif channel == "WxPusher":
                            use_WxPusher = True
                        print(f"自定义设定启用{channel}进行通知...")
    
    # 检查通知内容关键字匹配分组
    if desp:
        for group_num in range(2, 20):
            env_name = f'NOTIFY_INCLUDE_TEXT{group_num}'
            if env_name in os.environ:
                include_keywords = os.environ[env_name].split('&')
                for keyword in include_keywords:
                    if keyword in desp:
                        print(f"检测到内容中包含关键字 '{keyword}'，将推送到分组{group_num}")
                        UseGroupNotify = group_num
                        break
    
    # 应用分组配置
    if UseGroupNotify != 1:
        suffix = str(UseGroupNotify)
        GOBOT_URL = os.environ.get(f'GOBOT_URL{suffix}', GOBOT_URL)
        GOBOT_TOKEN = os.environ.get(f'GOBOT_TOKEN{suffix}', GOBOT_TOKEN)
        GOBOT_QQ = os.environ.get(f'GOBOT_QQ{suffix}', GOBOT_QQ)
        SCKEY = os.environ.get(f'PUSH_KEY{suffix}', SCKEY)
        WP_APP_TOKEN = os.environ.get(f'WP_APP_TOKEN{suffix}', WP_APP_TOKEN)
        WP_TOPICIDS = os.environ.get(f'WP_TOPICIDS{suffix}', WP_TOPICIDS)
        WP_UIDS = os.environ.get(f'WP_UIDS{suffix}', WP_UIDS)
        WP_URL = os.environ.get(f'WP_URL{suffix}', WP_URL)
        BARK_PUSH = os.environ.get(f'BARK_PUSH{suffix}', BARK_PUSH)
        BARK_SOUND = os.environ.get(f'BARK_SOUND{suffix}', BARK_SOUND)
        BARK_GROUP = os.environ.get(f'BARK_GROUP{suffix}', BARK_GROUP)
        TG_BOT_TOKEN = os.environ.get(f'TG_BOT_TOKEN{suffix}', TG_BOT_TOKEN)
        TG_USER_ID = os.environ.get(f'TG_USER_ID{suffix}', TG_USER_ID)
        DD_BOT_TOKEN = os.environ.get(f'DD_BOT_TOKEN{suffix}', DD_BOT_TOKEN)
        DD_BOT_SECRET = os.environ.get(f'DD_BOT_SECRET{suffix}', DD_BOT_SECRET)
        QYWX_KEY = os.environ.get(f'QYWX_KEY{suffix}', QYWX_KEY)
        QYWX_AM = os.environ.get(f'QYWX_AM{suffix}', QYWX_AM)
        IGOT_PUSH_KEY = os.environ.get(f'IGOT_PUSH_KEY{suffix}', IGOT_PUSH_KEY)
        PUSH_PLUS_TOKEN = os.environ.get(f'PUSH_PLUS_TOKEN{suffix}', PUSH_PLUS_TOKEN)
        PUSH_PLUS_USER = os.environ.get(f'PUSH_PLUS_USER{suffix}', PUSH_PLUS_USER)
        GOTIFY_URL = os.environ.get(f'GOTIFY_URL{suffix}', GOTIFY_URL)
        GOTIFY_TOKEN = os.environ.get(f'GOTIFY_TOKEN{suffix}', GOTIFY_TOKEN)
        GOTIFY_PRIORITY = int(os.environ.get(f'GOTIFY_PRIORITY{suffix}', GOTIFY_PRIORITY))
        BNCR_HOST = os.environ.get(f'BncrHost{suffix}', BNCR_HOST)
        BNCR_TOKEN = os.environ.get(f'BncrToken{suffix}', BNCR_TOKEN)
    
    # 备注名称替换
    if ShowRemarkType != "1" and strTitle not in os.environ.get('NOTIFY_SKIP_NAMETYPELIST', '').split('&'):
        print("处理账号Remark...")
        envs = await getEnvs()
        for env in envs:
            cookie = env.get('value', '')
            pt_pin = unquote(re.search(r'pt_pin=([^;\s]+)', cookie).group(1)) if cookie else ""
            remark = getRemark(env.get('remarks', ''))
            
            if remark:
                if ShowRemarkType in ['2', '3']:
                    new_name = f"{pt_pin}({remark})"
                else:
                    new_name = remark
                
                # 替换文本中的用户名
                text = text.replace(pt_pin, new_name)
                
                # 资产变动通知特殊处理
                if text in ["京东资产变动", "京东资产变动#2", "京东资产变动#3", "京东资产变动#4"]:
                    parts = desp.split('🎏🎏🎏🎏🎏🎏🎏🎏🎏🎏🎏🎏🎏')
                    if len(parts) == 2:
                        # 第一部分是提示信息，第二部分是详细内容
                        # 在详细内容中替换用户名
                        detailed_content = parts[1].replace(pt_pin, new_name)
                        desp = parts[0] + '🎏🎏🎏🎏🎏🎏🎏🎏🎏🎏🎏🎏🎏' + detailed_content
                        # 添加青龙面板信息
                        created = env.get('createdAt') or env.get('created')
                        updated = env.get('updatedAt') or env.get('timestamp') or env.get('updated')
                        ql_info = getQLinfo(cookie, created, updated, env.get('remarks', ''))
                        if ql_info:
                            desp += f"\n{ql_info}"
    
    # 实际发送通知
    print(f"最终通知标题: {strTitle}")
    print(f"通知内容: {desp}")
    
    # 发送到各种通知渠道
    if SCKEY and use_serverNotify:
        print("通过Server酱发送通知")
        try:
            requests.post(f"https://sc.ftqq.com/{SCKEY}.send", 
                         data={"text": strTitle, "desp": desp}, timeout=10)
        except Exception as e:
            print(f"Server酱通知失败: {str(e)}")
    
    if TG_BOT_TOKEN and TG_USER_ID and use_tgBotNotify:
        print("通过Telegram发送通知")
        try:
            url = f"https://{TG_API_HOST}/bot{TG_BOT_TOKEN}/sendMessage"
            payload = {
                "chat_id": TG_USER_ID,
                "text": f"{strTitle}\n\n{desp}",
                "disable_web_page_preview": True
            }
            proxies = {}
            if TG_PROXY_HOST and TG_PROXY_PORT:
                proxies = {
                    "http": f"http://{TG_PROXY_HOST}:{TG_PROXY_PORT}",
                    "https": f"http://{TG_PROXY_HOST}:{TG_PROXY_PORT}"
                }
            requests.post(url, data=payload, proxies=proxies, timeout=10)
        except Exception as e:
            print(f"Telegram通知失败: {str(e)}")
    
    if BARK_PUSH and use_BarkNotify:
        print("通过Bark发送通知")
        try:
            bark_url = f"{BARK_PUSH}/{urllib.parse.quote(strTitle)}/{urllib.parse.quote(desp)}"
            if BARK_SOUND:
                bark_url += f"?sound={BARK_SOUND}"
            if BARK_GROUP:
                bark_url += f"&group={BARK_GROUP}" if "?" in bark_url else f"?group={BARK_GROUP}"
            requests.get(bark_url, timeout=10)
        except Exception as e:
            print(f"Bark通知失败: {str(e)}")
    
    if DD_BOT_TOKEN and use_ddBotNotify:
        print("通过钉钉发送通知")
        try:
            timestamp = str(round(time.time() * 1000))
            secret_enc = DD_BOT_SECRET.encode('utf-8')